﻿using System;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

 namespace RuoTeng.Win32
{
    class Window : RuoTeng.Win32.Message
    {

    ///<summary>【Win32 API】 隐藏窗口</summary>
        public const int SW_HIDE   =0;
    ///<summary>【Win32 API】 正常显示窗口</summary>
        public const int SW_SHOWNORMAL = 1;
        public const int SW_NORMAL = 1;
        public const int SW_SHOWMINIMIZED = 2;
        public const int SW_SHOWMAXIMIZED = 3;
        public const int SW_MAXIMIZE = 3;
        public const int SW_SHOWNOACTIVATE = 4;
        public const int SW_SHOW = 5;
        public const int SW_MINIMIZE = 6;
        public const int SW_SHOWMINNOACTIVE = 7;
        public const int SW_SHOWNA = 8;
        public const int SW_RESTORE = 9;
        public const int SW_SHOWDEFAULT = 10;
        public const int SW_FORCEMINIMIZE = 11;
        public const int SW_MAX = 11;

        public const uint WM_CLOSE = 0x0010;

       public struct ENUMHWND
       {
             public string ClassName;
             public string WindowTitle;
             public IntPtr[]  Hwnd;
             public int    Number;
             public bool   ClassNameRegex;
             public bool   WindowTitleRegex;
       }
       public delegate bool WNDENUMPROC(IntPtr hWnd, ref ENUMHWND enumHwnd);

       private struct Rectangle
        {
          public int left;
          public int top;
          public int right;
          public int bottom;
        }
     /// <summary>
     /// 【Win32 API】 查看查询窗口
     /// </summary>
     /// <param name="className">类名</param>
     /// <param name="windowName">标题</param>
     /// <returns>窗口句柄</returns>
        [DllImport("user32.dll",EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindow(string className, string windowName);
   
    /// <summary>
    /// 【Win32 API】 检测窗口是否最小化
    /// </summary>
    /// <param name="hWnd">窗口句柄</param>
    /// <returns></returns>
        [DllImport("user32.dll")]   
        public static extern bool IsIconic(IntPtr hWnd);
   
    /// <summary>
    /// 【Win32 API】 该函数检索指定的对话框中的控制句柄
    /// </summary>
    /// <param name="hDlg">标识含有控制的对话框</param>
    /// <param name="nlDDlgltem">指定将被检索的控制标识符</param>
    /// <returns>如果函数调用成功则返回值为给定控制的窗口句柄。如果函数调用失败，则返回值为NULL</returns>
        [DllImport("user32.dll", EntryPoint = "GetDlgltem")]
        public static extern IntPtr GetDlgltem(IntPtr hDlg, int nlDDlgltem);
   
    /// <summary>
    /// 【Win32 API】 这个函数查找子窗口
    /// </summary>
    /// <param name="hwndParent">要查找子窗口的父窗口句柄 NULL，则函数以桌面窗口为父窗口，查找桌面窗口的所有子窗口</param>
    /// <param name="hwndChildAfter">
    ///          子窗口句柄。查找从在Z序中的下一个子窗口开始 如果HwndChildAfter为NULL，
    ///          查找从hwndParent的第一个子窗口开始如果hwndParent 和 hwndChildAfter同时为NULL，
    ///          则函数查找所有的顶层窗口及消息窗口
    /// </param>
    /// <param name="className">
    ///          指向一个指定了类名的空结束字符串，或一个标识类名字符串的成员的指针。
    ///          如果该参数为一个成员，则它必须为前次调用theGlobaIAddAtom函数产生的全局成员。
    ///          该成员为16位，必须位于lpClassName的低16位，高位必须为0
    /// </param>
    /// <param name="windowName">
    ///          指向一个指定了窗口名（窗口标题）的空结束字符串。如果该参数为 NULL，则为所有窗口全匹配。返回值：
    ///          如果函数成功，返回值为具有指定类名和窗口名的窗口句柄。如果函数失败，返回值为NULL
    /// </param>
    /// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string windowName);

    /// <summary>
    ///【Win32 API】 该函数设置指定窗口的显示状态
    /// </summary>
    /// <param name="hWnd">指窗口句柄</param>
    /// <param name="nCmdShow">
    ///         nCmdShow：指定窗口如何显示。如果发送应用程序的程序提供了STARTUPINFO结构，则应用程序第一次调用ShowWindow时该参数被忽略。否则，在第一次调用ShowWindow函数时，该值应为在函数WinMain中nCmdShow参数。在随后的调用中，该参数可以为下列值之一： 　
    ///         SW_FORCEMINIMIZE：在WindowNT5.0中最小化窗口，即使拥有窗口的线程被挂起也会最小化。在从其他线程最小化窗口时才使用这个参数。
    ///         SW_HIDE：隐藏窗口并激活其他窗口。 　
    ///         SW_MAXIMIZE：最大化指定的窗口。 　
    ///         SW_MINIMIZE：最小化指定的窗口并且激活在Z序中的下一个顶层窗口。 　
    ///         SW_RESTORE：激活并显示窗口。如果窗口最小化或最大化，则系统将窗口恢复到原来的尺寸和位置。在恢复最小化窗口时，应用程序应该指定这个标志。 
    ///         SW_SHOW：在窗口原来的位置以原来的尺寸激活和显示窗口。 　
    ///         SW_SHOWDEFAULT：依据在STARTUPINFO结构中指定的SW_FLAG标志设定显示状态，
    ///         STARTUPINFO 结构是由启动应用程序的程序传递给CreateProcess函数的。 　
    ///         SW_SHOWMAXIMIZED：激活窗口并将其最大化。 　
    ///         SW_SHOWMINIMIZED：激活窗口并将其最小化。 　　
    ///         SW_SHOWMINNOACTIVATE：窗口最小化，激活窗口仍然维持激活状态。 　
    ///         SW_SHOWNA：以窗口原来的状态显示窗口。激活窗口仍然维持激活状态。 
    ///         SW_SHOWNOACTIVATE：以窗口最近一次的大小和状态显示窗口。激活窗口仍然维持激活状态。 
    ///         SW_SHOWNORMAL：激活并显示一个窗口。如果窗口被最小化或最大化，系统将其恢复到原来的尺寸和大小。应用程序在第一次显示窗口的时候应该指定此标志。
    /// </param>
    /// <returns>如果窗口以前可见，则返回值为非零。如果窗口以前被隐藏，则返回值为零</returns>
        [DllImport("user32.dll",EntryPoint = "ShowWindow")]
        public static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
        
    /// <summary>
    ///【Win32 API】  该函数将指定的窗口设置到Z序的顶部。如果窗口为顶层窗口，则该窗口被激活；如果窗口为子窗口，则相应的顶级父窗口被激活
    /// </summary>
    /// <param name="hWnd">设置到Z序的顶部的窗口句柄</param>
    /// <returns>如果函数成功，返回值为非零；如果函数失败，返回值为零</returns>
        [DllImport("user32.dll", EntryPoint = "BringWindowToTop")]
        public static extern bool BringWindowToTop(IntPtr hWnd);

    /// <summary>
    /// 【Win32 API】  该函数返回z序中的前一个或后一个窗口的句柄。下一窗口在指定窗口的下面，前一窗口则在上面。如果指定的窗口是顶端窗口，
    /// 该函数返回下一个（或前一个）顶端窗口的句柄。如果指定的窗口是顶层窗口，函数返回下一个（或前一个）顶层窗口的句柄。
    /// 如果函数是子窗口，则函数搜索下一个或前一个子窗口的句柄
    /// </summary>
    /// <param name="hWnd">一个窗口的句柄。窗口句柄在wCmd参数的基础上获得的相对于这个窗口的句柄</param>
    /// <param name="wCmd">wCmd:指明窗口返回的是前一窗口的句柄还是后一窗口的句柄。该参数可以是下列两个值之一： 　
    ///                    GW_HWNDNEXT：返回在给定窗口的下面窗口的句柄。 
    ///                    GW_HWNDPREV：返回在给定窗口的上面窗口的句柄。
    ///                    GW_HWNDFIRST = 0;
    ///                    GW_HWNDLAST = 1;
    ///                    GW_HWNDNEXT = 2;
    ///                    GW_HWNDPREV = 3;
    ///                    GW_OWNER = 4;
    ///                    GW_CHILD = 5;
    /// </param>
    /// <returns>如果函数成功，返回值是前一窗口（或后一窗口）的句柄。如果前后窗口不存在，则返回值为NULL</returns>
        [DllImport("user32.dll", EntryPoint = "GetNextWindow")]
        public static extern IntPtr GetNextWindow(IntPtr hWnd,uint wCmd);
   
    /// <summary>
    ///【Win32 API】  销毁指定的窗口。这个函数通过发送WM_DESTROY 消息和 WM_NCDESTROY 消息使窗口无效并移除其键盘焦点。
    /// 这个函数还销毁窗口的菜单，清空线程的消息队列，销毁与窗口过程相关的定时器，解除窗口对剪贴板的拥有权，打断剪贴板器的查看链
    /// </summary>
    /// <param name="hWnd">将被销毁的窗口的句柄</param>
    /// <returns>如果函数成功，返回值为非零：如果函数失败，返回值为零</returns>
        [DllImport("user32.dll", EntryPoint = "DestroyWindow")]
        public static extern bool DestroyWindow(IntPtr hWnd);

   /// <summary>
   /// 【Win32 API】  改变指定窗口的位置和大小.对顶窗口来说,位置和大小取决于屏幕的左上角;对子窗口来说,位置和大小取决于父窗口客户区的左上角. 
   /// </summary>
   /// <param name="hWnd">hWnd指定了窗口的句柄 </param>
   /// <param name="X">指定了CWnd的左边的新位置</param>
   /// <param name="Y">指定了CWnd的顶部的新位置</param>
   /// <param name="nWidth">指定了CWnd的新宽度</param>
   /// <param name="nHeight">指定了CWnd的新高度</param>
   /// <param name="bRepaint">指定了是否要重画CWnd。如果为TRUE，则CWnd象通常那样在OnPaint消息处理函数中接收到一条WM_PAINT消息。
   ///        如果这个参数为FALSE，则不会发生任何类型的重画操作。这应用于客户区、非客户区（包括标题条和滚动条）和由于CWnd移动而露出的父窗口的任何部分。
   ///        当这个参数为FALSE的时候，应用程序必须明确地使CWnd和父窗口中必须重画的部分无效或重画
   /// </param>
   /// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "MoveWindow")]
        public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
  
  /// <summary>
  /// 【Win32 API】 该函数枚举所有屏幕上的顶层窗口，办法将窗口句柄传送给应用程序定义的回调函数。
  ///  回调函数返回FALSE将停止枚举，否则EnumWindows函数继续到所有顶层窗口枚举完为止
  /// </summary>
  /// <param name="hWnd">指向一个应用程序定义的回调函数指针</param>
  /// <param name="eachHWND">指定一个传递给回调函数的应用程序定义值</param>
  /// <returns>如果函数成功，返回值为非零；如果函数失败，返回值为零</returns>
  /// <remarks>EnumWindows函数不列举子窗口</remarks>
        [DllImport("user32.dll", EntryPoint = "EnumWindows")]
        public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, ref ENUMHWND enumHwnd);
        
  /// <summary>
  ///【Win32 API】 枚举一个父窗口的所有子窗口
  /// </summary>
  /// <param name="hWndParent">父窗口句柄 </param>
  /// <param name="lpEnumFunc"> 回调函数的地址 </param>
  /// <param name="eachHWND">你自己定义的参数</param>
  /// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "EnumChildWindows")]
        public static extern bool EnumChildWindows(IntPtr hWndParent, WNDENUMPROC lpEnumFunc,ref ENUMHWND enumHwnd);
 
  /// <summary>
  ///【Win32 API】 该函数获得指定窗口所属的类的类名
  /// </summary>
  /// <param name="hWnd">窗口的句柄及间接给出的窗口所属的类</param>
  /// <param name="className">指向接收窗口类名字符串的缓冲区的指针</param>
  /// <param name="nMaxCount">指定由参数lpClassName指示的缓冲区的字节数。如果类名字符串大于缓冲区的长度，则多出的部分被截断</param>
  /// <returns>如果函数成功，返回值为拷贝到指定缓冲区的字符个数：如果函数失败，返回值为0</returns>
        [DllImport("user32.dll", EntryPoint = "GetClassName")]
        public static extern int GetClassName(IntPtr hWnd, IntPtr lpClassName, int nMaxCount);
  
  /// <summary>
  /// 【Win32 API】 　该函数将指定窗口的标题条文本（如果存在）拷贝到一个缓存区内。如果指定的窗口是一个控件，则拷贝控件的文本。
  ///  但是，GetWindowText不能接收在其他应用程序中的控件的文本
  /// </summary>
  /// <param name="hWnd">带文本的窗口或控件的句柄</param>
  /// <param name="windowText">指向接收文本的缓冲区的指针</param>
  /// <param name="nMaxCount">指定要保存在缓冲区内的字符的最大个数，其中包含NULL字符。如果文本超过界限，它就被截断</param>
  /// <returns>如果函数成功，返回值是拷贝的字符串的字符个数，不包括中断的空字符；
  ///          如果窗口无标题栏或文本，或标题栏为空，或窗口或控制的句柄无效，则返回值为零。若想获得更多错误信息，请调用GetLastError函数。 　
  ///          函数不能返回在其他应用程序中的编辑控件的文本
  /// </returns>
  /// <remarks>
  ///   如果目标窗口属于当前进程，GetWindowText函数给指定的窗口或控件发送WM_GETTEXT消息。
  ///   如果目标窗口属于其他进程，并且有一个窗口标题，则GetWindowTeXt返回窗口的标题文本，如果窗口无标题，则函数返回空字符串
  /// </remarks>
        [DllImport("user32.dll", EntryPoint = "GetWindowText")]
        public static extern int GetWindowText(IntPtr hWnd, IntPtr lpWindowText, int nMaxCount);
  
 /// <summary>
 /// 【Win32 API】 该函数返回指定窗口的边框矩形的尺寸。该尺寸以相对于屏幕坐标左上角的屏幕坐标给出
 /// </summary>
 /// <param name="hWnd">窗口句柄</param>
 /// <param name="lpRect">指向一个RECT结构的指针，该结构接收窗口的左上角和右下角的屏幕坐标</param>
 /// <returns>返回值：如果函数成功，返回值为非零：如果函数失败，返回值为零</returns>
        [DllImport("user32.dll", EntryPoint = "GetWindowRect")]
        private static extern bool _GetWindowRect(IntPtr hWnd, out Rectangle lpRect);

        public  static bool GetWindowRect(IntPtr hWnd, out System.Drawing.Rectangle lpRect)
        {
            Rectangle _lpRect;
            bool result = _GetWindowRect(hWnd, out _lpRect);
            lpRect = new System.Drawing.Rectangle();
            if (result)
            {              
               lpRect = System.Drawing.Rectangle.FromLTRB(_lpRect.left,_lpRect.top,_lpRect.right,_lpRect.bottom);
            }
            return result;

        }
 
 /// <summary>
 /// 【Win32 API】  该函数获取窗口客户区的坐标。客户区坐标指定客户区的左上角和右下角。由于客户区坐标是相对窗口客户区的左上角而言的，因此左上角坐标为（0，0）
 /// </summary>
 /// <param name="hWnd">窗口的句柄</param>
 /// <param name="lpRect">是一个指针，指向一个RECT类型的rectangle结构。该结构有四个LONG字段,分别为left、top、right和bottom。
 ///         GetClientRect将这四个字段设定为窗口显示区域的尺寸。left和top字段通常设定为0。
 ///         right和bottom字段设定为显示区域的宽度和高度（像素点数）也可以是一个CRrect对象指针。CRect对象有多个参数，与RECT用法相同
 /// </param>
 /// <returns>如果函数成功，返回一个非零值</returns>
        [DllImport("user32.dll", EntryPoint = "GetClientRect")]
        private static extern bool _GetClientRect(IntPtr hWnd,out Rectangle lpRect);

        public static bool GetClientRect(IntPtr hWnd, out System.Drawing.Rectangle lpRect)
        {
            Rectangle _lpRect;
            bool result = _GetClientRect(hWnd, out _lpRect);
            lpRect = new System.Drawing.Rectangle();
            if (result)
            {
                lpRect = System.Drawing.Rectangle.FromLTRB(_lpRect.left, _lpRect.top, _lpRect.right, _lpRect.bottom);
            }
            return result;

        }

 /// <summary>
 ///【Win32 API】 该函数改变指定窗口的标题栏的文本内容（如果窗口有标题栏）。如果指定窗口是一个控件，则改变控件的文本内容。
 ///             然而，SetWindowText函数不改变其他应用程序中的控件的文本内容
 /// </summary>
 /// <param name="hWnd">要改变文本内容的窗口或控件的句柄</param>
 /// <param name="lpString">指向一个空结束的字符串的指针，该字符串将作为窗口或控件的新文本</param>
 /// <returns>如果函数成功，返回值为非零；如果函数失败，返回值为零</returns>
 /// <remarks>
 ///          如果目标窗口属于当前进程，SetWindowText函数会使WM_SETTEXT消息发送给指定的窗口或控件。
 ///          然而，如果控件是以WS_CAPTION风格创建的列表框控件，SetWindowText函数将为控件设置文本，而不是为列表项设置文本
 /// </remarks>
        [DllImport("user32.dll", EntryPoint = "SetWindowText")]
        public static extern bool SetWindowText(IntPtr hWnd, IntPtr lpString);

 /// <summary>
 ///【Win32 API】 该函数获得给定窗口的可视状态
 /// </summary>
 /// <param name="hWnd">被测试窗口的句柄</param>
 /// <returns>
 ///        如果指定的窗口及其父窗口具有WS_VISIBLE风格，返回值为非零；如果指定的窗口及其父窗口不具有WS_VISIBLE风格，返回值为零。
 ///        由于返回值表明了窗口是否具有Ws_VISIBLE风格，因此，即使该窗口被其他窗口遮盖，函数返回值也为非零
 /// </returns>
 /// <remarks>
 ///       窗口的可视状态由WS_VISIBLE位指示。当设置了WS_VISIBLE位，窗口就可显示，而且只要窗口具有WS_VISIBLE风格，任何画在窗口的信息都将被显示
 /// </remarks>
        [DllImport("user32.dll", EntryPoint = "IsWindowVisible")]
        public static extern bool IsWindowVisible(IntPtr hWnd);

 /// <summary>
 ///【Win32 API】  该函数确定给定的窗口句柄是否标识一个已存在的窗口
 /// </summary>
 /// <param name="hWnd">被测试窗口的句柄</param>
 /// <returns>如果窗口句柄标识了一个已存在的窗口，返回值为非零；如果窗口句柄未标识一个已存在窗口，返回值为零</returns>
        [DllImport("user32.dll")]
        public static extern bool IsWindow(IntPtr hWnd);

 /// <summary>
 ///   设置窗口的标题
 /// </summary>
 /// <param name="hWnd">窗口句柄</param>
 /// <param name="text">更新个文本</param>
 /// <returns>如果更新成功返回非零,失败返回零</returns>   
        public static bool SetText(IntPtr hWnd, string text)
        {  
            IntPtr intPtr= Marshal.StringToHGlobalAnsi(text);
            bool   result=SetWindowText(hWnd, intPtr);
            Marshal.FreeHGlobal(intPtr);
            return result; 
        }
 
 /// <summary>
 ///   添加窗口句柄指针
 /// </summary>
 /// <param name="array">原有的窗口句柄数组</param>
 /// <param name="element">需要添加的窗口句柄</param>
 /// <returns>返回添加后的新的窗口句柄数组</returns>
        private static IntPtr[] PushHwnd(IntPtr[] array, IntPtr element)
        {
            IntPtr[] newArray = new IntPtr[array.Length + 1];
            Array.Copy(array, newArray, array.Length);
            newArray[array.Length] = element;
            return newArray;
        }

 /// <summary>
 ///  枚举窗口句柄回调函数
 /// </summary>
 /// <param name="hWnd">句柄</param>
 /// <param name="enumHwnd">附加对象</param>
 /// <returns>如果返回True继续枚举窗口 如果返回false 终止枚举窗口</returns>
        private static bool EnumWindowsProc(IntPtr hWnd,ref ENUMHWND enumHwnd)
        {
            if (hWnd != IntPtr.Zero)
            { 
                if ((enumHwnd.ClassName == null || enumHwnd.ClassName == "") && (enumHwnd.WindowTitle == null || enumHwnd.WindowTitle == ""))
                {
                    enumHwnd.Hwnd = PushHwnd(enumHwnd.Hwnd, hWnd);
                }
                else
                {
                    if (enumHwnd.ClassName != null && enumHwnd.ClassName != "")
                    {
                        string className = GetClassName(hWnd);                       
                        if (className == "")
                        {
                            return true;
                        }
                        else
                        {  
                            if (!enumHwnd.ClassNameRegex && className != enumHwnd.ClassName)
                            {
                                return true;
                            }
                            else if (!Regex.IsMatch(className, enumHwnd.ClassName, RegexOptions.IgnoreCase))
                            {
                                return true;
                            }
                        }
                    }
                    if (enumHwnd.WindowTitle != null && enumHwnd.WindowTitle != "")
                    {
                        string windowTitle = GetText(hWnd);
                        if (windowTitle == "")
                        {
                            return true;
                        }
                        else
                        {
                            if (!enumHwnd.WindowTitleRegex && windowTitle != enumHwnd.WindowTitle)
                            {
                                return true;
                            }
                            else if (!Regex.IsMatch(windowTitle, enumHwnd.WindowTitle, RegexOptions.IgnoreCase))
                            {
                                return true;
                            }
                        }
                    }
                    enumHwnd.Hwnd = PushHwnd(enumHwnd.Hwnd, hWnd);
                }
                return enumHwnd.Hwnd.Length < enumHwnd.Number ? true : false;
            }
            return true;
        }

/// <summary>
///  重载函数正则模糊 查询符合条件的父窗口,当找的符合的,立即退出
/// </summary>
/// <param name="className">类名</param>
/// <param name="windowTitle">标题</param>
/// <returns>成功返回找的的窗口句柄失败返回空指针</returns>
       
        public static IntPtr FindRegex(string className, string windowTitle)
        {
            IntPtr[] hwnd =FindRegex(className,windowTitle,1,false,true);  ;
            return hwnd.Length > 0 ? hwnd[0] : IntPtr.Zero;
        }

 /// <summary>
 /// 重载函数 正则模糊 查询符合条件的父窗口
 /// </summary>
 /// <param name="className">类名</param>
 /// <param name="windowTitle">标题</param>
 /// <param name="all">是否返回有的符合条件的句柄</param>
 /// <returns>成功返回找的的窗口句柄数组</returns>
        public static IntPtr[] FindRegex(string className, string windowTitle, bool all)
        {
            int maxNumber = all ? 1000 : 1; 
            return  FindRegex(className,windowTitle,1000,false,true);        
        }

/// <summary>
/// 重载函数 正则模糊 查询符合条件的父窗口
/// </summary>
/// <param name="className">类名</param>
/// <param name="windowTitle">标题</param>
/// <param name="maxNumber">返回最大句柄数目</param>
/// <param name="classNameRegex">类型查询是否启用正则匹配</param>
/// <param name="windowTitleRegex">标题查询是否启用正则匹配</param>
/// <returns>成功返回找的的窗口句柄数组</returns>
        public static IntPtr[] FindRegex(string className, string windowTitle, int maxNumber, bool classNameRegex, bool windowTitleRegex)
        {
            WNDENUMPROC lpEnumFunc = new WNDENUMPROC(EnumWindowsProc);
            ENUMHWND enumHwnd = new ENUMHWND();
            enumHwnd.ClassName = className;
            enumHwnd.WindowTitle = windowTitle;
            enumHwnd.Hwnd = new IntPtr[0];
            enumHwnd.Number = maxNumber;
            enumHwnd.ClassNameRegex = false;
            enumHwnd.WindowTitleRegex=true;
            EnumWindows(lpEnumFunc,ref enumHwnd);
            return enumHwnd.Hwnd;          
        }

        /// <summary>
        ///  重载函数正则模糊 查询符合条件的子窗口,当找的符合的,立即退出
        /// </summary>
        /// <param name="className">类名</param>
        /// <param name="windowTitle">标题</param>
        /// <returns>成功返回找的的窗口句柄失败返回空指针</returns>
        public static IntPtr FindChildRegex(IntPtr hwndParent,string className, string windowTitle)
        {
            IntPtr[] hwnd = FindChildRegex(hwndParent,className, windowTitle, 1, false, true); ;
            return hwnd.Length > 0 ? hwnd[0] : IntPtr.Zero;
        }

        /// <summary>
        /// 重载函数 正则模糊 查询符合条件的子窗口
        /// </summary>
        /// <param name="className">类名</param>
        /// <param name="windowTitle">标题</param>
        /// <param name="all">是否返回有的符合条件的句柄</param>
        /// <returns>成功返回找的的窗口句柄数组</returns>
        public static IntPtr[] FindChildRegex(IntPtr hwndParent, string className, string windowTitle, bool all)
        {
            int maxNumber = all ? 1000 : 1;
            return FindChildRegex(hwndParent, className, windowTitle, maxNumber, false, true); ;
        }

        /// <summary>
        /// 重载函数 正则模糊 查询符合条件的子窗口
        /// </summary>
        /// <param name="className">类名</param>
        /// <param name="windowTitle">标题</param>
        /// <param name="maxNumber">返回最大句柄数目</param>
        /// <param name="classNameRegex">类型查询是否启用正则匹配</param>
        /// <param name="windowTitleRegex">标题查询是否启用正则匹配</param>
        /// <returns>成功返回找的的窗口句柄数组</returns>
        public static IntPtr[] FindChildRegex(IntPtr hwndParent, string className, string windowTitle, int maxNumber, bool classNameRegex, bool windowTitleRegex)
        {
            WNDENUMPROC lpEnumFunc = new WNDENUMPROC(EnumWindowsProc);
            ENUMHWND enumHwnd = new ENUMHWND();
            enumHwnd.ClassName = className;
            enumHwnd.WindowTitle = windowTitle;
            enumHwnd.Hwnd = new IntPtr[0];
            enumHwnd.Number = maxNumber;
            enumHwnd.ClassNameRegex = false;
            enumHwnd.WindowTitleRegex = true;
            EnumChildWindows(hwndParent, lpEnumFunc, ref enumHwnd);
            return enumHwnd.Hwnd;
        }

        /// <summary>
        ///  根据句柄获取文本
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <returns>成功返回文本失败返回空字符串</returns>
        public static string GetText(IntPtr hWnd)
        {
            string text="";
            IntPtr intPtr = (IntPtr)Marshal.AllocHGlobal(1024);//给指针分配结构体大小的内存空间  
            GetWindowText(hWnd, intPtr, 1024);
            text = Marshal.PtrToStringAnsi(intPtr);
            Marshal.FreeHGlobal(intPtr);   
            return text;
        }

        /// <summary>
        ///  根据句柄获取类名
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <returns>成功返回文本失败返回空字符串</returns>
        public static string GetClassName(IntPtr hWnd)
        {
            string text = "";
            IntPtr intPtr = (IntPtr)Marshal.AllocHGlobal(1024);//给指针分配结构体大小的内存空间  
            GetClassName(hWnd, intPtr, 1024);
            text = Marshal.PtrToStringAnsi(intPtr);
            Marshal.FreeHGlobal(intPtr);
            return text;
        }

        /// <summary>
        ///  窗口最大化
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <returns></returns>
        public static int Max(IntPtr hWnd)
        {
            return ShowWindow(hWnd,SW_MAXIMIZE);
        }

        /// <summary>
        ///  窗口最小化
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <returns></returns>
        public static int Min(IntPtr hWnd)
        {
            return ShowWindow(hWnd, SW_MINIMIZE);
        }

        /// <summary>
        ///  关闭窗口
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <returns></returns>
        public static int Close(IntPtr hWnd)
        {
            return SendMessage(hWnd,WM_CLOSE,0,0);
        }

        /// <summary>
        ///  隐藏窗口
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <returns></returns>
        public static int Hide(IntPtr hWnd)
        {
            return ShowWindow(hWnd, SW_HIDE);
        }

        /// <summary>
        ///  显示窗口
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <returns></returns>
        public static int Show(IntPtr hWnd)
        {
            return ShowWindow(hWnd, SW_SHOW);
        }

        /// <summary>
        ///  还原窗口
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <returns></returns>
        public static int Restore(IntPtr hWnd)
        {
            return ShowWindow(hWnd, SW_RESTORE);
        }

        /// <summary>
        ///  窗口置顶
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <returns></returns>
        public static bool Top(IntPtr hWnd)
        {  
            return BringWindowToTop(hWnd);
        }

        /// <summary>
        ///  向窗口发送键盘敲击字符事件
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <param name="msg">字符</param>
        /// <returns></returns>
        public static int SendKeyPress(IntPtr hWnd, char msg)
        {
            return PostMessage(hWnd,KeyBoard.WM_CHAR, msg, 0x0);
        }

        /// <summary>
        ///  向窗口发送键盘敲击字符事件
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <param name="msg">字符的值</param>
        /// <returns></returns>
        public static int SendKeyPress(IntPtr hWnd, int msg)
        {
            return PostMessage(hWnd, KeyBoard.WM_CHAR, msg, 0x0);
        }

        /// <summary>
        ///  向窗口发送键盘按下事件
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <param name="msg">键盘字符</param>
        /// <returns></returns>
        public static int SendKeyDown(IntPtr hWnd, char msg)
        {
            return PostMessage(hWnd, KeyBoard.WM_KEYDOWN, msg, 0x0);
        }

        /// <summary>
        ///  向窗口发送键盘弹起事件
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <param name="msg">键盘字符</param>
        /// <returns></returns>
        public static int SendKeyUp(IntPtr hWnd, char msg)
        {
            return PostMessage(hWnd, KeyBoard.WM_KEYUP, msg, 0x0);
        }

        /// <summary>
        ///  向窗口发送键字符串文本
        /// </summary>
        /// <param name="hWnd">句柄</param>
        /// <param name="msg">字符串文本</param>
        /// <returns></returns>
        public static int SendString(IntPtr hWnd, string msg)
        {
            byte[] bytes = System.Text.Encoding.Default.GetBytes(msg);
            foreach (byte bt in bytes)
            {
                KeyBoard.PressKey(hWnd,(int)bt);
            }
            return 0;
        }

       /// <summary>
       ///  判断该句柄的所属进程ID与指定的进程是否一样
       /// </summary>
       /// <param name="hWnd">句柄</param>
       /// <param name="processId">进程ID</param>
       /// <returns>一样返回true 不一样返回false</returns>
        public static bool IsProcess(IntPtr hWnd, IntPtr processId)
        {                  
            IntPtr __destProcessId= IntPtr.Zero;
            Sys.GetWindowThreadProcessId(hWnd, out __destProcessId);
            return (__destProcessId != IntPtr.Zero && processId == __destProcessId) ?  true  :  false;
        }

    }     
}
